import functools
import os
import threading
import sys
# from typing import Dict, Any

import logging

from logging.config import fileConfig

import datetime

# import json

import schedule
# from pymongo.cursor import Cursor

# from schedule import every, repeat, run_pending

import time

# from functools import wraps

import configparser

from datetime import datetime, timedelta

# import hashlib

from mongo.MongoHelper import MongoHelper

from findata.akshare.AkshareWeekly import AkshareWeekly
# from findata.akshare.AkshareDaily import AkshareDaily
# from findata.akshare.AkshareQuarterly import AkshareQuarterly
# from findata.akshare.AkshareMonthly import AkshareMonthly
# from findata.akshare.AkshareBiWeekly import AkshareBiWeekly
# from findata.akshare.AkshareYearly import AkshareYearly
from findata.mairui.freeData import equity_list
from tools.mail.mail import emailUtils
from tools.log.logU import logU

fileConfig('logging_config.ini', disable_existing_loggers=False)
logger = logging.getLogger('simple_example')
mongoHelper = None


def catch_exceptions(cancel_on_failure=False):
    def catch_exceptions_decorator(job_func):
        @functools.wraps(job_func)
        def wrapper(*args, **kwargs):
            try:
                return job_func(*args, **kwargs)
            except Exception:
                import traceback
                print(traceback.format_exc())
                if cancel_on_failure:
                    return schedule.CancelJob
        return wrapper
    return catch_exceptions_decorator


# This decorator can be applied to
def with_logging(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('LOG: Running job "%s"' % func.__name__)
        result = func(*args, **kwargs)
        print('LOG: Job "%s" completed' % func.__name__)
        return result
    return wrapper


def the_job():
    while True:
        print('The job is running')
        logger.info("================================")


def the_job2():
    while True:
        print('The job2 is also running')
        logger.info("################################")


cfgdir = os.path.split(os.path.realpath(__file__))[0]
print(cfgdir)
cfg = os.path.join(cfgdir, 'config.cfg')

#
config = configparser.ConfigParser()
if len(sys.argv) >= 2:
    config.read(sys.argv[1])
else:
    config.read('./config.cfg')
database = config.get('db', 'database')
myUrl = config.get('db', 'url')
mongoHelper = MongoHelper(url=myUrl, database=database)

akshareWeekly = AkshareWeekly(cfg=cfg)


def last_day_of_quarter(year, quarter):
    # 每个季度的最后一个月，第三个参数是月份的最后一天
    months = ((1, 3, 31), (4, 6, 30), (7, 9, 30), (10, 12, 31))
    # 季度是从1开始的，所以减1来获取正确的月份
    month = months[quarter - 1]
    # 使用年份和季度的最后一个月来创建datetime对象
    return datetime(year, month[1], month[2])


@with_logging
@catch_exceptions(cancel_on_failure=True)
def get_his():
    e_list = akshareWeekly.get_all_equities()
    for rec in e_list:
        akshareWeekly.a_hist(
            symbol=rec['code'],
            period='daily',
            start_date='20240706',
            end_date='20240712',
            adjust='hfq')
        akshareWeekly.a_hist(
            symbol=rec['code'],
            period='daily',
            start_date='20240706',
            end_date='20240712',
            adjust='qfq')
        akshareWeekly.a_hist(
            symbol=rec['code'],
            period='daily',
            start_date='20240706',
            end_date='20240712',
            adjust='')


def get_equity_list():
    equity_list()


@with_logging
@catch_exceptions(cancel_on_failure=True)
def get_lending_list():
    akshareWeekly.lending_securities(code=akshareWeekly.get_all_equities())


@with_logging
@catch_exceptions(cancel_on_failure=True)
def get_repurchase_list():
    akshareWeekly.equity_repurchase()


def get_free_holder_list():
    e_list = akshareWeekly.get_all_equities()
    logging.info(f"{len(e_list)} freeholders")
    t = 0
    for record in e_list:
        t += 1
        logging.info(f"第 {t} 个")
        for item in range(2014, 2024):
            for ele in range(1, 4):
                akshareWeekly.free_holder(
                    exchange=record['exchange'],
                    code=record['code'],
                    beg_date=last_day_of_quarter(
                        item,
                        ele).strftime('%Y%m%d'))


def get_retail_investor_list():
    for item in range(2014, 2024):
        for ele in range(1, 4):
            akshareWeekly.num_of_retail_investor(
                symbol=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))


def get_market_fund_flow():
    akshareWeekly.market_fund_flow()


def get_big_deal():
    akshareWeekly.big_deal_track()


def get_holder_decrease():
    akshareWeekly.holder(symbol='全部')


def get_pledge_ratio():
    # 定义开始日期
    start_date = datetime(2023, 6, 1)
    # 定义结束日期
    end_date = datetime(2024, 7, 30)
    # 生成日期范围
    date_range = [
        start_date +
        timedelta(
            days=i) for i in range(
            (end_date -
             start_date).days +
            1)]
    # 打印日期范围
    for p_date in date_range:
        akshareWeekly.pledge_ratio(beg_date=p_date.strftime("%Y%m%d"))


def get_block_transaction_details():
    akshareWeekly.block_transaction_details(
        symbol='A股', beg_date='20240101', end_date='20240630')
    akshareWeekly.block_transaction_details(
        symbol='B股', beg_date='20240101', end_date='20240630')
    akshareWeekly.block_transaction_details(
        symbol='基金', beg_date='20240101', end_date='20240630')


def get_core_biz():
    emailUtils.simplysend(
        receiver=['liuchuang@9tts.cn'],
        title='核心业务',
        content='定时器启动')
    for record in akshareWeekly.get_all_equities():
        akshareWeekly.core_biz(
            symbol=record['code'],
            exchange=record['exchange'])


def get_financing_securities():
    # 定义开始日期
    start_date = datetime(2024, 6, 1)
    # 定义结束日期
    end_date = datetime(2024, 6, 30)
    # 生成日期范围
    date_range = [
        start_date +
        timedelta(
            days=i) for i in range(
            (end_date -
             start_date).days +
            1)]
    # 打印日期范围
    for p_date in date_range:
        akshareWeekly.financing_securities(data=p_date.strftime("%Y%m%d"))


def get_institute_holding():
    print(int(datetime.now().strftime('%Y')))
    for item in range(2010, int(datetime.now().strftime('%Y'))):
        akshareWeekly.institute_holding(symbol=str(item) + '1')
        akshareWeekly.institute_holding(symbol=str(item) + '2')
        akshareWeekly.institute_holding(symbol=str(item) + '3')
        akshareWeekly.institute_holding(symbol=str(item) + '4')


def get_individual_cash_flow():
    # emailUtils.simplysend(receiver=['liuchuang@9tts.cn'], title=f'个股资金流-{datetime.now().strftime("%Y-%m-%d")}', content='个股资金流开始同步')
    all_equity = akshareWeekly.get_all_equities()
    data = [0]*len(all_equity)
    for seq, record in enumerate(all_equity):
        res = akshareWeekly.individual_cash_flow(
          code=record['code'], market=record['exchange'])

        data[seq] = res[0]

    emailUtils.simplysend(receiver=['liuchuang@9tts.cn'], title=f'个股资金流-{datetime.now().strftime("%Y-%m-%d")}',
                          content=f'{sum(data)}条记录')


def get_cash_flow():
    for item in range(2010, int(datetime.now().strftime('%Y'))):
        for ele in range(1, 4):
            akshareWeekly.cash_flow(
                beg_date=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))


def get_asset_balance():
    for item in range(2010, int(datetime.now().strftime('%Y'))):
        for ele in range(1, 4):
            akshareWeekly.asset_balance(
                beg_date=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))


def get_profit():
    for item in range(2010, int(datetime.now().strftime('%Y'))):
        for ele in range(1, 4):
            akshareWeekly.profit(
                beg_date=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))


def get_holdings_by_fund():
    data = [0] * 6
    for item in range(2020, int(datetime.now().strftime('%Y'))):
        for ele in range(1, 4):

            res = akshareWeekly.fund_holder(
                symbol='基金持仓', beg_date=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))
            data[0] = data[0] + res[0] if res is not None and res[0] is not None else 0
            res = akshareWeekly.fund_holder(
                symbol='QFII持仓', beg_date=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))
            data[1] = data[1] + res[0] if res is not None and res[0] is not None else 0
            res = akshareWeekly.fund_holder(
                symbol='社保持仓', beg_date=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))
            data[2] = data[2] + res[0] if res is not None and res[0] is not None else 0
            res = akshareWeekly.fund_holder(
                symbol='券商持仓', beg_date=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))
            data[3] = data[3] + res[0] if res is not None and res[0] is not None else 0
            res = akshareWeekly.fund_holder(
                symbol='保险持仓', beg_date=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))
            data[4] = data[4] + res[0] if res is not None and res[0] is not None else 0
            res = akshareWeekly.fund_holder(
                symbol='信托持仓', beg_date=last_day_of_quarter(
                    item, ele).strftime('%Y%m%d'))
            data[5] = data[5] + res[0] if res is not None and res[0] is not None else 0
    emailUtils.simplysend(
        receiver=['a467241@163.com'],
        title='基金持股信息更新',
        content=f'{sum(data)}条记录')


def get_industry_cash_flow():
    data = [0] * 5
    res = akshareWeekly.industry_cash_flow(symbol='即时')
    data[0] = data[0] + res[0] if res is not None and res[0] is not None else 0
    res = akshareWeekly.industry_cash_flow(symbol='3日排行')
    data[1] = data[1] + res[0] if res is not None and res[0] is not None else 0
    res = akshareWeekly.industry_cash_flow(symbol='5日排行')
    data[2] = data[2] + res[0] if res is not None and res[0] is not None else 0
    res = akshareWeekly.industry_cash_flow(symbol='10日排行')
    data[3] = data[3] + res[0] if res is not None and res[0] is not None else 0
    res = akshareWeekly.industry_cash_flow(symbol='20日排行')
    data[4] = data[4] + res[0] if res is not None and res[0] is not None else 0
    emailUtils.simplysend(
        receiver=['liuchuang@9tts.cn'],
        title='行业资金流信息',
        content=f'{sum(data)}条记录')


def get_institute_research():
    # 定义开始日期
    start_date = datetime(2024, 6, 1)
    # 定义结束日期
    end_date = datetime(2024, 6, 30)
    # 生成日期范围
    date_range = [
        start_date +
        timedelta(
            days=i) for i in range(
            (end_date -
             start_date).days +
            1)]
    # 打印日期范围
    for p_date in date_range:
        akshareWeekly.institute_research(beg_date=p_date.strftime("%Y%m%d"))


def get_federal_interest_rate():
    akshareWeekly.usa_bank_interest_rate()


def get_some_free_holder_list():
    clist = [{'code': '601179', 'exchange': 'sh'}, {'code': '601138', 'exchange': 'sh'},
             {'code': '002281', 'exchange': 'sz'}, {'code': '002156', 'exchange': 'sz'},
             {'code': '002889', 'exchange': 'sz'}]

    logging.info(f"{len(clist)} freeholders")

    t = 0
    for record in clist:
        t += 1
        logging.info(f"第 {t} 个")
        for item in range(2014, 2024):
            for ele in range(1, 4):
                akshareWeekly.free_holder(
                    exchange=record['exchange'],
                    code=record['code'],
                    beg_date=last_day_of_quarter(
                        item,
                        ele).strftime('%Y%m%d'))


def run_threaded(job_func):
    job_thread = threading.Thread(target=job_func)
    job_thread.start()


def all_job():
    # schedule.every().day.at("23:12:00").do(run_threaded, get_cash_flow)
    schedule.every().saturday.at("14:12:00").do(run_threaded, get_cash_flow)
    # schedule.every().day.at("23:12:00").do(run_threaded, get_profit)
    schedule.every().saturday.at("15:12:00").do(run_threaded, get_profit)
    schedule.every().day.at("23:12:00").do(run_threaded, get_equity_list)
    schedule.every().day.at("23:12:00").do(run_threaded, get_his)
    schedule.every().day.at("23:12:00").do(run_threaded, get_individual_cash_flow)
    schedule.every().day.at("23:12:00").do(run_threaded, get_institute_holding)
    # schedule.every().day.at("23:12:00").do(run_threaded, get_core_biz)
    schedule.every().sunday.at("13:00:00").do(run_threaded, get_core_biz)
    schedule.every().day.at("23:12:00").do(run_threaded, get_financing_securities)
    schedule.every().day.at("23:12:00").do(run_threaded, get_lending_list)
    schedule.every().day.at("23:12:00").do(run_threaded, get_block_transaction_details)
    schedule.every().day.at("23:12:00").do(run_threaded, get_pledge_ratio)
    schedule.every().day.at("23:12:00").do(run_threaded, get_holder_decrease)
    schedule.every().day.at("23:12:00").do(run_threaded, get_big_deal)
    schedule.every().day.at("23:12:00").do(run_threaded, get_repurchase_list)
    schedule.every().day.at("23:12:00").do(run_threaded, get_free_holder_list)
    # schedule.every().day.at("23:12:00").do(run_threaded, get_retail_investor_list)
    schedule.every().wednesday.at("11:12:00").do(run_threaded, get_retail_investor_list)
    schedule.every().day.at("23:12:00").do(run_threaded, get_free_holder_list)
    # schedule.every().day.at("23:12:00").do(run_threaded, get_asset_balance)
    schedule.every().saturday.at("11:12:00").do(run_threaded, get_asset_balance)
    # schedule.every().day.at("23:12:00").do(run_threaded, get_federal_interest_rate)
    schedule.every().monday.at("23:12:00").do(run_threaded,get_federal_interest_rate)
    schedule.every().day.at("23:12:00").do(run_threaded, get_industry_cash_flow)
    # schedule.every().day.at("23:12:00").do(run_threaded, get_institute_research)
    schedule.every().thursday.at("10:12:00").do(run_threaded, get_institute_research)
    schedule.every().day.at("23:12:00").do(run_threaded, get_holdings_by_fund)

    while True:
        schedule.run_pending()
        time.sleep(1)


if __name__ == '__main__':

    cfgdir = os.path.split(os.path.realpath(__file__))[0]
    print(cfgdir)
    cfg = os.path.join(cfgdir, 'config.cfg')
    print(cfg)
    emailUtils(cfg=cfg)
    logU(cfg=cfgdir)

    # 使用lambda函数来包装你的任务和它的参数
    # schedule.every(10).seconds.do(lambda: job("Alice", 30))
    # schedule.every(10).seconds.do(my_job,name='Alice',age=30)
    # schedule.every().monday.do(theJob)
    # schedule.every(10).seconds.do(theJob)
    # 每十分钟执行任务
    # schedule.every(2).minutes.do(theJob)
    # 每个小时执行任务
    # schedule.every().hour.do(theJob)
    # 每天的10:30执行任务
    # schedule.every().day.at("21:50:00").do(lambda: akshareWeekly.basicInfo(symbol='600487'))
    # schedule.every().day.at("23:10:00").do(lambda: get_equity_list())
    # schedule.every().day.at("23:10:00").do(lambda: get_his())
    # schedule.every().day.at("23:10:00").do(lambda: get_individual_cash_flow())
    # schedule.every().day.at("12:50:00").do(lambda: get_institute_holding())
    # schedule.every().day.at("23:10:00").do(lambda: get_core_biz())
    # schedule.every().day.at("23:10:00").do(lambda: get_financing_securities())
    # schedule.every().day.at("00:46:00").do(lambda: get_lending_list())
    # schedule.every().day.at("23:10:00").do(lambda: get_block_transaction_details())
    # schedule.every().day.at("00:44:00").do(lambda: get_pledge_ratio())
    # schedule.every().day.at("23:10:00").do(lambda: get_holder_decrease())
    # schedule.every().day.at("12:10:00").do(lambda: get_big_deal())
    # schedule.every().day.at("00:35:00").do(lambda: get_repurchase_list())
    # schedule.every().day.at("23:10:00").do(lambda: get_free_holder_list())
    # schedule.every().day.at("12:03:00").do(lambda: get_retail_investor_list())
    # schedule.every().day.at("23:10:00").do(lambda: get_free_holder_list())
    # schedule.every().day.at("23:10:00").do(lambda: get_asset_balance())
    # schedule.every().day.at("23:10:00").do(lambda: get_cash_flow())
    # schedule.every().day.at("23:10:00").do(lambda: get_profit())
    # schedule.every().day.at("23:10:00").do(lambda: get_federal_interest_rate())
    # schedule.every().day.at("09:26:00").do(lambda: get_industry_cash_flow())
    # schedule.every().day.at("23:10:00").do(lambda: get_institute_research())
    # schedule.every().day.at("12:50:00").do(lambda: get_holdings_by_fund())

    logU.get_logger("Schedule")
    get_individual_cash_flow()
    all_job()


    # get_pledgeRatio()

    # get_asset_balance()
    # get_instituteHolding()
    # get_core_biz()
    # get_retail_investor_list()

    # 每个月执行任务
    # schedule.every().monday.do(theJob)
    # 每个星期三的13:15分执行任务
    # schedule.every().wednesday.at("13:15").do(theJob)
    # 每分钟的第17秒执行任务
    # schedule.every().minute.at(":17").do(theJob)
    # do() 将额外的参数传递给job函数
    # schedule.every(2).seconds.do(greet, name='Alice')
    # all_jobs = schedule.get_jobs()

    # .tag 打标签
    # schedule.every().day.do(greet, 'Andrea').tag('daily-tasks', 'friend')

    # 每个小时运行作业，2030-01-01 18:33 today
    # schedule.every(1).hours.until("2030-01-01 18:33").do(job)

    # 每个小时运行作业，8个小时后停止
    # schedule.every(1).hours.until(timedelta(hours=8)).do(job)
    # schedule.clear()
    # while True:
    #     schedule.run_pending()
    #     time.sleep(1)
